AWS CDKのパッケージのバージョンはCDKプロジェクト内で揃えるようにしよう!
こんにちは、CX事業本部の若槻です。
今回は、AWS CDKのパッケージのバージョンはCDKプロジェクト内で揃えるようにしよう!、という話です。
先に結論
- CDKパッケージのバージョンはCDKプロジェクト内では揃えるようにすると無用な不具合を回避できる
- パッケージの追加は
npm install <パッケージ>@<バージョン> --save-exact
のようにするとバージョンを固定できる
CDKスタックのLambdaリソースで型エラーが発生する
CDKプロジェクトを作成して下記のようなLambda Functionリソースを含むCDKスタックを作成しました。
import * as cdk from "@aws-cdk/core"; import * as cloudfront from "@aws-cdk/aws-cloudfront"; import * as s3 from "@aws-cdk/aws-s3"; import * as s3deploy from "@aws-cdk/aws-s3-deployment"; import * as iam from "@aws-cdk/aws-iam"; import * as lambda from "@aws-cdk/aws-lambda"; export class SampleAppStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const sampleFunction = new lambda.Function(this, "SampleFunction", { code: lambda.Code.asset("lambda/sample-lambda"), handler: "index.handler", runtime: lambda.Runtime.NODEJS_14_X, timeout: cdk.Duration.seconds(5), }); //略 } }
するとLambda Functionリソースのプロパティのうちtimeout
で型エラーが発生していました。
エラーの内容を読んでも何が悪いんだかよく分かりません。
Type 'import("/Users/wakatsuki.ryuta/projects/local/aws-cdk-deploy-react/node_modules/@aws-cdk/core/lib/duration").Duration' is not assignable to type 'import("/Users/wakatsuki.ryuta/projects/local/aws-cdk-deploy-react/node_modules/@aws-cdk/aws-cloudfront/node_modules/@aws-cdk/core/lib/duration").Duration'. Types have separate declarations of a private property 'amount'.ts(2322) function.d.ts(69, 14): The expected type comes from property 'timeout' which is declared here on type 'FunctionProps' (property) FunctionOptions.timeout?: Duration | undefined The function execution time (in seconds) after which Lambda terminates the function. Because the execution time affects cost, set this value based on the function's expected execution time. @default Duration.seconds(3) @stability — stable
原因調査、解決
この時のpackage.json
が下記のようになります。よく見ると他のCDKのNodeパッケージが1.111.0
または^1.111.0
であるのに対し、@aws-cdk/aws-lambda
のみ^1.112.0
とバージョンがずれています。
{ "name": "aws-cdk-deploy-react", "version": "0.1.0", "bin": { "aws-cdk-deploy-react": "bin/aws-cdk-deploy-react.js" }, "scripts": { "build": "tsc", "watch": "tsc -w", "test": "react-scripts test", "cdk": "cdk" }, "devDependencies": { "@aws-cdk/assert": "1.111.0", "@types/jest": "^26.0.10", "@types/node": "10.17.27", "aws-cdk": "1.111.0", "jest": "^26.4.2", "ts-jest": "^26.2.0", "ts-node": "^9.0.0", "typescript": "~3.9.7" }, "dependencies": { "@aws-cdk/aws-cloudfront": "^1.111.0", "@aws-cdk/aws-lambda": "^1.112.0", "@aws-cdk/aws-s3": "^1.111.0", "@aws-cdk/aws-s3-deployment": "^1.111.0", "@aws-cdk/core": "1.111.0", "source-map-support": "^0.5.16" } }
ずれている理由としては、Nodeパッケージをnpm install <パッケージ名>
のようにしてインストールすると、その時点の最新版のパッケージがインストールされます。よって他のCDKのパッケージより後にインストールした@aws-cdk/aws-lambda
のみバージョンが上がっていたため、不具合が起きていたのでしょうか。
% npm install @aws-cdk/aws-lambda
実際にインストールされているバージョンを確認してみると、1.113.0
と1.111.0
が混在しています。@aws-cdk/aws-lambda
は@aws-cdk/assert
や@aws-cdk/core
、aws-cdk
とバージョンがずれています。
% npm list --depth=0 aws-cdk-deploy-react@0.1.0 /Users/wakatsuki.ryuta/projects/local/aws-cdk-deploy-react ├── @aws-cdk/assert@1.111.0 ├── @aws-cdk/aws-cloudfront@1.113.0 ├── @aws-cdk/aws-lambda@1.113.0 ├── @aws-cdk/aws-s3-deployment@1.113.0 ├── @aws-cdk/aws-s3@1.113.0 ├── @aws-cdk/core@1.111.0 ├── @types/jest@26.0.24 ├── @types/node@10.17.27 ├── aws-cdk@1.111.0 (略)
そこで下記のようにバージョンを1.111.0
に指定して@aws-cdk/aws-lambda
をインストール(ダウングレード)してみます。(後述しますが、これは厳密なバージョン指定方法ではありません。)
% npm install @aws-cdk/aws-lambda@1.111.0
package.json
上で@aws-cdk/aws-lambda
が^1.111.0
となりました。
"dependencies": { "@aws-cdk/aws-cloudfront": "^1.111.0", "@aws-cdk/aws-lambda": "^1.111.0", "@aws-cdk/aws-s3": "^1.111.0", "@aws-cdk/aws-s3-deployment": "^1.111.0", "@aws-cdk/core": "1.111.0", "source-map-support": "^0.5.16" }
また@aws-cdk/aws-lambda
の実際のインストールバージョンも1.111.0
となっていました。
% npm list --depth=0 aws-cdk-deploy-react@0.1.0 /Users/wakatsuki.ryuta/projects/local/aws-cdk-deploy-react ├── @aws-cdk/assert@1.111.0 ├── @aws-cdk/aws-cloudfront@1.113.0 ├── @aws-cdk/aws-lambda@1.111.0 ├── @aws-cdk/aws-s3-deployment@1.113.0 ├── @aws-cdk/aws-s3@1.113.0 ├── @aws-cdk/core@1.111.0 ├── @types/jest@26.0.24 ├── @types/node@10.17.27 ├── aws-cdk@1.111.0 (略)
すると、Lambda Functionリソースのtimeout
のエラーは出なくなりました。
結果として、AWS CDKのパッケージのバージョンはCDKプロジェクト内で揃えるようにした方が良いようです。
Nodeパッケージのバージョンを固定する
Nodeパッケージのバージョニングはsemantic versioningであり、キャレット^
が付くと「最も大きな0でないバージョニングを変えない範囲」のバージョンとなります。またnpm install @aws-cdk/aws-lambda@1.111.0
のようにインストールすると既定で^
付きとなります。例えば^1.111.0
と指定された時のバージョンは1.111.0
または1.112.0
または1.113.0
を取りうるので厳密なバージョン指定はできません。よって今回のような不具合を極力回避するためには、CDKパッケージをインストールする際には^
を付けずにバージョンを固定してパッケージを管理する必要があります。
バージョンを固定してNodeパッケージをインストールしたい場合は、--save-exact
オプションを使用します。
--save-exact
を使用してCDKパッケージをインストールしてみます。
% npm install @aws-cdk/aws-lambda@1.111.0 --save-exact
するとpackage.json
上でも^
が付かない1.111.0
となりました。
"dependencies": { "@aws-cdk/aws-cloudfront": "^1.111.0", "@aws-cdk/aws-lambda": "1.111.0", "@aws-cdk/aws-s3": "^1.111.0", "@aws-cdk/aws-s3-deployment": "^1.111.0", "@aws-cdk/core": "1.111.0", "source-map-support": "^0.5.16" }
CDKパッケージを追加でインストールする場合は、既にあるほかのパッケージのバージョンに合わせて--save-exact
オプションを使用してインストールを行うようにすると良さそうですね。
以上